package com.itcast.peft.service;

import java.time.LocalDateTime;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.function.Predicate;
import java.util.stream.Stream;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.itcast.peft.config.MultipleModelConfig.ChatModelHolder;
import com.itcast.peft.entity.InteractionQuestion;
import com.itcast.peft.entity.InteractionReply;
import com.itcast.peft.entity.Question;
import com.itcast.peft.mapper.InteractionQuestionMapper;
import com.itcast.peft.mapper.InteractionReplyMapper;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.Data;

@Service
public class InteractionDataWasher {
    @Resource
    private ChatModelHolder userprefGenerationModelHolder;
    
    @Autowired
    private QuestionService questionService;

    @Autowired
    private AnswerService answerService;
    
    @Autowired
    private InteractionQuestionMapper interactionQuestionMapper;

    @Autowired
    private InteractionReplyMapper interactionReplyMapper;
    
    @Autowired
    private List<WashedDataRule> allRule;
    
    private Predicate<WashedData> targetRuleFilter;

    
    @PostConstruct
    void init() {
        this.targetRuleFilter = allRule.stream().reduce(WashedDataRule::and).orElseThrow();
    }
    /**
     * 从Interaction数据转换为之前用过的QA数据，此处需要分组并利用AI技术进行清洗
     * dataWash方法可以挂接到XXL等周期性触发服务上
     */
    public void dataWash(String startTime) {
        // 默认一周数据
        var createTime = Optional.ofNullable(startTime).map(LocalDateTime::parse)
                .orElseGet(() -> LocalDateTime.now().minusWeeks(1));

        LambdaQueryWrapper<InteractionQuestion> query = new LambdaQueryWrapper<>();
        // 划定时间范围
        query.gt(InteractionQuestion::getCreateTime, createTime);
        var original = interactionQuestionMapper.selectList(query);
        // 生成中间结果
        var washedData = original.stream().map(q -> {
            LambdaQueryWrapper<InteractionReply> repQuery = new LambdaQueryWrapper<>();
            repQuery.eq(InteractionReply::getQuestionId, q.getId());
            // 这里 我们保留最高赞
            var allReply = interactionReplyMapper.selectList(repQuery);
            var prefReply = allReply.stream()
                    .reduce((x, y) -> x.getLikedTimes() > y.getLikedTimes() ? x : y)
                    .orElseThrow();
            var washed = new WashedData();
            washed.setInteractionQuestion(q);
            washed.setPreferanceReply(prefReply);
            washed.setAllReply(allReply);
            return washed;
        })
        .filter(targetRuleFilter) //规则过滤
        .toList();
        
        // 拆分 QA ==> Train(80%) | Test(20%)
        var trainData = new LinkedList<WashedData>();
        var testData = new LinkedList<WashedData>();
        var rand = new Random();
        washedData.stream().forEach(w -> {
            var target = rand.nextInt(0, 100) > 80 ? testData : trainData;
            target.add(w);
        });
        Stream.of(trainData, testData).filter(l -> !l.isEmpty()).forEach(w -> {
            questionService.addWashedData(w);
            answerService.addWashedData(w, userprefGenerationModelHolder);
        });
    }
    
    @Data
    public static class WashedData {
        InteractionQuestion interactionQuestion;
        InteractionReply preferanceReply;
        List<InteractionReply> allReply;

        Question targetQuestion;
    }
    
    @FunctionalInterface
    public static interface WashedDataRule extends Predicate<WashedData> {
        default WashedDataRule and(WashedDataRule another) {
            return t -> this.test(t) && another.test(t);
        }
    }
}
